package com.chen.base.utils;

import com.chen.root.annotation.OrderNum;
import com.chen.base.inter.LinkNodeHandler;
import lombok.SneakyThrows;
import lombok.experimental.UtilityClass;
import org.springframework.util.Assert;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * 职责链工具类
 * @author: 陈锦龙
 * @date: 2023/4/10 15:32
 */
@UtilityClass
public class DutyLinkUtil {

    /**
     * 遍历链路
     * 链路中止条件：链路节点返回值不为Null
     * @param parentClass 父级的类对象
     * @param params 节点所需参数
     * @param target 返回值类型
     * @return 节点返回值
     */
    public <R> R run(Class<?> parentClass, Object params, Class<R> target) {
        return (R) run(parentClass, params);
    }

    /**
     * 遍历链路
     * 链路中止条件：链路节点返回值不为Null
     * @param parentClass 父级的类对象
     * @param params 节点所需参数
     * @return 节点返回值
     */
    @SneakyThrows
    public Object run(Class<?> parentClass, Object params) {
        // 获取bean集
        Assert.isTrue(parentClass != LinkNodeHandler.class,"parentClass错误");
        Map<String, ?> beanMap = SpringContextHolder.getAppContext().getBeansOfType(parentClass);
        List<Object> list = new ArrayList<>(beanMap.values());

        // 按@OrderNum注解排序
        list = StreamUtil.sort(list, obj -> {
            OrderNum orderNum = obj.getClass().getAnnotation(OrderNum.class);
            return orderNum != null ? orderNum.value() : Integer.MAX_VALUE;
        }, true);

        // 遍历各个节点
        for (Object node : list) {
            if (node instanceof LinkNodeHandler){
                Object invoke = ((LinkNodeHandler) node).handler(params);
                if (invoke != null){
                    return invoke;
                }
            }
        }
        return null;
    }

}
